package com.asiainfo.test

import scala.util.control.Breaks

/**
 * 基础语法回顾
 */
object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    println("-----------基本字符串输出及变量定义----------------")
        //定义变量
    var name:String = "duhongjiang";
    var age:Int = 21;

    //输出
    println(name)
    println(age)
    //通过${} 嵌入变量
    println(s"我的名字是${name},我的年龄是${age}")
    //通过百分号传值
    printf("我的是名字=>%s",name)

    //多行字符串
    println(
      """
        |select
        |*
        |from
        |user
        |where id=1
        |
        |""".stripMargin)

    //数据类型
    println("----------------数据类型---------------------")

    /**
     * Scala中一切数据都是对象，都是Any的子类。
     * Scala中数据类型分为两大类：数值类型（AnyVal）、 引用类型（AnyRef），不管是值类型还是引用类型都是对象。
     *  Scala数据类型仍然遵守，低精度的值类型向高精度值类型，自动转换（隐式转换）
     *  Unit：对应Java中的void，用于方法返回值的位置，表 示方法没有返回值。Unit是一个数据类型，只有一个对象 就是()。Void不是数据类型，只是一个关键字
     *
     */


    def speak(a:String):Unit={
      println(s"这是一个函数$a")
    }
    speak("duhongjiang")

    var a=0.1;
    var b=0.2
    //计算的时候会转化成double进行计算 结果是double 如果需要用float存储则需要强制转化
    var c:Float=(a+b).toFloat
    println(c)

    //short byte char 之间不能自动转化  计算时会转化成int进行计算

    var d:Short =(1.toShort+2.toShort).toShort
    println(d)


    println("-----------------运算符-------------------")

    /**
     * java:
     * 1、==比较两个变量本身的值，即两个对象在内存中的首地址；
     * 2、equals 比较字符串中所包含的内容是否相同。
     * scala
     * 1.==更加类似于 Java 中的 equals，参照 jd 工具
     * 2.eq只能用字符串比较
     */
    println(1.1==1.10)
    var e:String="1.1"
    var f:String="1.1"
    println(e.eq(f))

    //scala 没有++ -- 操作符 可以通过+= -=进行操作
    /**
     * scala 运算符的本质就是方法，scala一切皆对象。
     */

    val res1 = 1.+(2)
    println(res1)
    //当调用对象的方法时 .可以去掉
    val res2 = 1+(2)
    println(res2)
    //当参数只有一个时 括号可以去掉
    val res3 = 1+2
    println(res3)

    println( 2 toString)

    println("------流程控制--------------")

    var m:Int=32;
    //if 判断 与java一致
    if(m<18){
      println("未成年了")
    }else if(m>18 && m<30){
      println("中年人")
    }else{
      println("老年人")
    }

    //for循环
    /**
     * Scala 也为 for 循环这一常见的控制结构提供了非常多的特性，这些 for 循环的特性被称为 for 推导式或 for 表达式。
     * 1、1 to 10  1到10
     * 2、1 until 10  1到9
     * 3、循环守卫
     */
    for (i<- 1 to 9;j<- 1 to i){
        print(s"${i}*${j}=${i*j}\t")
        if(i==j){
          println()
        }
    }
    println("循环守卫")

    /**
     * 循环守卫，即循环保护式（也称条件判断式，守卫）。保护式为 true 则进入循环体内部，为false 则跳过，类似于continue。
     */
    for (i<-1 to 20;if i%2!=0){
      print(i+" ")
    }
    println()
    println("循环步长~~~")
    for (i<- 1 to 10 by 3){
      println(i)
    }
    /*
    for 推导式一行中有多个表达式时，所以要加 ; 来隔断逻辑
    for 推导式有一个不成文的约定：当 for 推导式仅包含单一表达式时使用圆括号，
    当包含多个表达式时，一般每行一个表达式，并用花括号代替圆括号
     */
    for {i<-1 to 2
        j<-1  to 5}{
      print(i+j)
    }

    //循环返回值是啥？ yield 返回的是一个数组列表Vector
    val res = for(i <- 1 to 10) yield i
    println()
    println(res.toList.sortBy(x=>x).reverse(0))

    /**
     * 需求将列表中基数+1返回
     */
    val result= for (i <- 1 to 10; if i % 2 != 0) yield {
      i + 1
    }
    println(result)

    //do while和while和java一致。
    //循环中断

    /**
     * break中断。
     */
    Breaks.breakable(
      for (i <- 1 to 10){
        if (i==5){
          Breaks.break();
        }
        println(i)
      }
    )

  println("--------------函数-----------------")

    //1.无参无返回值
    def hell()={
      println("这一个无参无返回值~~")
    }

    hell()
    //2.无参有返回值  默认scala最后一行就是返回值
    def get()={
      123
    }

    println(get)

    //3.有参无返回值
    def print1(a:String)={
      println(s"${a}++++")
    }
    print1("123")

    //4.有参有返回值
    def  dd(a:Int):Int={
      a+2
    }
    println(dd(4))


    //可变参数
    def add(a:Int,b:Int*): Int ={
      var sum=a
      for (i<- b){
        sum+=i
      }
      sum
    }
    println(add(1,2,3,4,5,6,7))

    //默认参数
    def aa(a:String,b:Int=10): Int ={
      a.toInt+b
    }

    println(aa("100"))
    //一般存在默认 参数 放最后  不然默认参数没有意义
    def bb(a:String="",b:Int): Int ={
      100
    }
//    println(bb(2))

    /**
     * scala的至简原则
     * 1、return 可以省略，Scala 会使用函数体的最后一行代码作为返回值
     * 2、如果函数体只有一行代码，可以省略花括号
     * 3、返回值类型如果能够推断出来，那么可以省略（:和返回值类型一起省略）
     * 4、如果有 return，则不能省略返回值类型，必须指定
     * 5、如果函数明确声明unit，那么即使函数体中使用 return 关键字也不起作用
     * 6、 Scala 如果期望是无返回值类型，可以省略等号
     * 7、如果函数无参，但是声明了参数列表，那么调用时，小括号，可加可不加
     * 8、如果函数没有参数列表，那么小括号可以省略，调用时小括号必须省略
     * 9、如果不关心名称，只关心逻辑处理，那么函数名（def）可以省略
     *
     */
    def compute(a:Int,b:Int):Int={
     return a+b
    }
    //默认情况scala最后一行是返回值 return省略
    def compute1(a:Int,b:Int):Int={
      a+b
    }
    //如果类型能够自动推断可以省略
    def compute2(a:Int,b:Int)={
      a+b
    }
    //如果函数体只有一行 可以省略花括号
    def compute3(a:Int,b:Int)=a+b

    //调用时
    println(compute3(1,2))

    //函数可以当作值复制给变量  如果无法推断类型时 需要用 _
    var va=compute3 _
    //如果显示指定变量类型可以不用_
    var vb:(Int,Int)=>Int = compute3
    println(va(1,2))

    //函数可以当作参数
    def com(a:(Int,Int)=>Int,b:Int,c:Int)={
      a(b,c)
    }
    println(com((a,b)=>{a+b},100,2))

    //柯里化、闭包







  }
}
